package com.wechat.wechat.lock;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

/**
 * Redis的分布式锁
 * @author NN
 * @2020/3/1 9:34
 */
@Component
@Slf4j
public class RedisLock {
    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * 加锁
     * key 锁名 value 锁值 当前时间+超时时间
     */
    public boolean lock(String key,String value)
    {
        //1.如果redis中没有锁，则加锁
        if(redisTemplate.opsForValue().setIfAbsent(key,value))
        {
            return true;
        }

        //2.处理死锁-redis中有锁，但是可能锁的时间已经过期了
        String currentValue = redisTemplate.opsForValue().get(key);
        //如果锁过期了
        if(!StringUtils.isEmpty(currentValue)
            &&Long.parseLong(currentValue)<System.currentTimeMillis())
        {
            //获取过期锁的时间，并将当前锁时间设置进去
            String oldValue = redisTemplate.opsForValue().getAndSet(key,value) ;
            //这边是防止两个线程同时访问这个方法时，要保证只有一个线程可以拿到锁
            if(!StringUtils.isEmpty(oldValue) && oldValue.equals(currentValue))
            {
                return true;
            }
        }
        return false;
    }
    /**
     * 解锁
     */
    public void unlock(String key,String value){
        try{
            String currentValue = redisTemplate.opsForValue().get(key);
            if(!StringUtils.isEmpty(currentValue) && currentValue.equals(currentValue))
            {
                //删除redis中锁的值
                redisTemplate.opsForValue().getOperations().delete(key);
            }
        }catch(Exception e){
            log.error("【redis分布式锁】解锁异常,{}",e);
        }


    }

}
